#-*- coding: utf-8 -*-
from google.appengine.ext import webapp, db
from google.appengine.api import urlfetch, users
from google.appengine.ext.webapp.util import run_wsgi_app
import base64
import twitterclient
import twitterdb
import urlparse
import logging
import hashlib
import urllib
import re
import cgi

class ApiHandler(webapp.RequestHandler):
    def post(self):
        #
        logging.debug('Method = "POST"')
        logging.debug('body:%s'%self.request.body)
        (scm, netloc, path, params, query, _) = urlparse.urlparse(self.request.url)
        logging.debug('path = %s, params= %s, query = %s'%(path, params, query))
        basic_auth_head=""
        try:
            basic_auth_head = self.request.headers['Authorization'].strip()
        except:
            logging.debug('no Authenticate')
            basic_auth_head=""
        basic_auth = ""
        try:
            logging.debug('header=%s'%self.request.headers)
        except:
            logging.debug('log header error!')
##        logging.debug('url = %s'%self.request.url)
##        logging.debug('%s'%basic_auth_head)
        if basic_auth_head:
            logging.debug('start')
            index = basic_auth_head.find('Basic')
            logging.debug('index=%s\n'%index)
            if index != -1:
                basic_auth = basic_auth_head[index+5:].strip()
                basic_auth = base64.b64decode(basic_auth)
                basic_auth_info = basic_auth.split(':')
                UserName = basic_auth_info[0]
                UserPwd  = basic_auth_info[1]
                md5obj = hashlib.md5()
                md5obj.update(UserPwd)
                UserPwdDigest  = md5obj.hexdigest()
                res = twitterdb.TwitterAuthdb.all().filter('UserName =',
                                                 UserName).filter(
                                                     'UserPwdDigest =',
                                                     UserPwdDigest)
                res2 = twitterdb.TwitterAuthdb.all().filter('UserName =', UserName)
                if res.count() > 0:
                    twUserInfo=res[0]
                    logging.debug('UserName=%s<br/>'%twUserInfo.UserName)
                    logging.debug('UserPwd=%s<br/>'%twUserInfo.UserPwdDigest)
                    logging.debug('Token=%s<br/>'%twUserInfo.Token)
                    logging.debug('Token_KEY=%s<br/>'%twUserInfo.Token_Secret)
                else:
                    logging.debug('UserName=%s<br/>'%UserName)
                    logging.debug('UserPwd=%s<br/>'%UserPwd)
                    #return
                    twUserInfo=twitterdb.TwitterAuthdb(UserName=UserName, \
                                         UserPwdDigest=UserPwd, \
                                         Token=None, \
                                         Token_Secret=None)
                if twUserInfo.Token:
                    #
                    logging.debug('exist token :%s'%twUserInfo.Token)
                else:
                    twUserInfo = self.getOAuth(twUserInfo, twUserInfo.UserName, UserPwd, UserPwdDigest)
                if twUserInfo.Token:
                    oaClient = twitterclient.OAuth('')
                    oaClient.TOKEN_KEY = twUserInfo.Token
                    oaClient.TOKEN_SECRET = twUserInfo.Token_Secret
                    if path.startswith('/1/'):
                        url = "https://api.twitter.com" + path
                    else:
                        if path.startswith('/api/'):
                            path = path[4:]
                        url = "https://api.twitter.com/1" + path
                    if self.request.body:
                        if params:
                            params += '&'
                        params += (self.request.body)
                    else:
                        params = query
                    authHeader = oaClient.getAuthHeader('POST', url, params)
                    if query:
                        url = "https://api.twitter.com/1" + path + '?' + query
                    body_dic = cgi.parse_qs(self.request.body)
                    base_str = "&".join(["%s=%s" % (urllib.quote(k,'-._~'), urllib.quote(body_dic[k][0],'-._~'))
                                for k in (body_dic)])
                    authHeader.update({'Content-Type':'application/x-www-form-urlencoded'})
                    try:
                        result = urlfetch.fetch(url=url, \
                                    payload=base_str, \
                                    method=urlfetch.POST, \
                                    headers=authHeader)
                    except:
                        logging.debug('fetch error, url = %s'%url)
                        self.response.set_status(500)
                        return
                    if result.status_code == 200:
                        self.response.headers=result.headers
                        self.response.out.write('%s'%result.content)
                        #logging.debug('content: %s'%result.content)
                        #logging.debug('truncated = %s'%result.content_was_truncated)
                    else:
                        #logging.debug('fetch status_code = %s'%result.status_code)
                        #logging.debug('error msg = %s'%result.content)
                        self.response.set_status(result.status_code)
                        self.response.out.write('%s'%result.content)
                else:
                    self.response.out.write('error')
            else:
                self.response.out.write("error")
        else:
            self.response.out.write("No Header")
                    
    def get(self):
        #
        (scm, netloc, path, params, query, _) = urlparse.urlparse(self.request.url)
        basic_auth_head=""
        if not 'Authorization' in  self.request.headers:
            logging.debug('No Authorization')
            self.getSearch(path, query)
            return 
        try:
            basic_auth_head = self.request.headers['Authorization'].strip()
        except:
            logging.debug('no Authenticate')
            basic_auth_head=""
        basic_auth = ""
        if basic_auth_head:
            index = basic_auth_head.find('Basic')
            if index != -1:
                basic_auth = basic_auth_head[index+5:].strip()
                basic_auth = base64.b64decode(basic_auth)
                basic_auth_info = basic_auth.split(':')
                UserName = basic_auth_info[0]
                UserPwd  = basic_auth_info[1]
                md5obj = hashlib.md5()
                md5obj.update(UserPwd)
                UserPwdDigest  = md5obj.hexdigest()
                res = twitterdb.TwitterAuthdb.all().filter('UserName =',
                                                 UserName).filter(
                                                     'UserPwdDigest =',
                                                     UserPwdDigest)
                res2 = twitterdb.TwitterAuthdb.all().filter('UserName =', UserName)
                if res.count() > 0:
                    twUserInfo=res[0]
##                    logging.debug('UserName=%s<br/>'%twUserInfo.UserName)
##                    logging.debug('Token=%s<br/>'%twUserInfo.Token)
##                    logging.debug('Token_KEY=%s<br/>'%twUserInfo.Token_Secret)
                else:
##                    logging.debug('UserName=%s<br/>'%UserName)
##                    logging.debug('UserPwd=%s<br/>'%UserPwd)
                    #return
                    twUserInfo=twitterdb.TwitterAuthdb(UserName=UserName, \
                                         UserPwdDigest=UserPwd, \
                                         Token=None, \
                                         Token_Secret=None)
                if twUserInfo.Token:
                    #
                    logging.debug('exist token :%s'%twUserInfo.Token)
                else:
                    twUserInfo = self.getOAuth(twUserInfo, twUserInfo.UserName, UserPwd, UserPwdDigest)
                if twUserInfo.Token:
                    oaClient = twitterclient.OAuth('')
                    oaClient.TOKEN_KEY = twUserInfo.Token
                    oaClient.TOKEN_SECRET = twUserInfo.Token_Secret
                    if path.startswith('/1/'):
                        url = "https://api.twitter.com" + path
                    else:
                        if path.startswith('/api/'):
                            path = path[4:]
                        url = "https://api.twitter.com/1" + path
                    if params:
                        if query:
                            params +='&' + query
                    else:
                        params = query
                    authHeader = oaClient.getAuthHeader('GET', url, params)
                    url += '?' + query
                    try:
                        result = urlfetch.fetch(url=url, \
                                    payload=params, \
                                    method=urlfetch.GET, \
                                    headers=authHeader)
                    except:
                        logging.debug('fetch error, url = %s'%url)
                    if result.status_code == 200:
                        self.response.headers=result.headers
##                        logging.debug('truncated = %s'%result.content_was_truncated)
                        self.response.out.write('%s'%result.content)
##                        logging.debug('%d'%len(result.content))
##                        logging.debug('content : %s'%result.content)
                    else:
                        logging.debug('fetch status_code = %s'%result.status_code)
                else:
                    self.response.out.write('error')
            else:
                self.response.out.write("error")
        else:
            self.response.out.write("No Header")
    def getOAuth(self, twUserInfo, UserName, UserPwd, UserPwdDigest):
        oaClient = twitterclient.OAuth('','oob')
        request_header = oaClient.getRequestToken()
##        logging.debug('  %s  '%request_header)
##        logging.debug('  %s  '%request_header["Authorization"])
##        logging.debug('request headers= %s'%request_header)
##        logging.debug('  %s  '%oaClient.REQUEST_TOKEN_URL)
        try:
            result = urlfetch.fetch(url=oaClient.REQUEST_TOKEN_URL, \
                                    payload=None, \
                                    method=urlfetch.POST, \
                                    headers=request_header)
        except:
            logging.debug('  %s  '%oaClient.REQUEST_TOKEN_URL)
##        logging.debug("%s"%result.content)
        if result.status_code == 200:
##            logging.debug('first_step content: %s'%result.content)
            token_arr=result.content.split('&')
            token = token_arr[0].split('=')[1]
            secret = token_arr[1].split('=')[1]
##            logging.debug('token = %s, secret = %s'%(token, secret))
            oaClient.TOKEN_KEY=token
            oaClient.TOKEN_SECRET=secret
        else:
            #error
            logging.debug('error')
            token = ""
        postFields={
            "user_id":UserName,
            "user_pwd":UserPwd,
            "addrlink":oaClient.AUTHORIZATION_URL+'?='+ token
            }
        postData=urllib.urlencode(postFields)
        verifiercode = self.getVerifier(UserName, UserPwd, token)
        oaClient.OAUTH_VERIFIER = verifiercode
        token_header = oaClient.getAccessToken()
        result = urlfetch.fetch(url=oaClient.ACCESS_TOKEN_URL, \
                                payload=None, \
                                method=urlfetch.POST, \
                                headers=token_header)
##        logging.debug('%s'%result.content)
        token_arr = result.content.split('&')
        twUserInfo.Token=token_arr[0].split('=')[1]
        twUserInfo.Token_Secret=token_arr[1].split('=')[1]
        twUserInfo.UserPwdDigest=UserPwdDigest
        twUserInfo.put()
        return twUserInfo
    def getVerifier(self, user_id, user_pwd, oauth_token):
        oauth_url = "https://api.twitter.com/oauth/authorize?oauth_token=%s"%oauth_token
        rep = urlfetch.fetch(oauth_url)
##        logging.debug("oauth_url:"+oauth_url)
##        logging.debug("rep_staut_code:%d"%rep.status_code)
        if rep.status_code == 200:
            authenticity_token_arr = re.findall('"\w{40}"', rep.content)
            authenticity_token = authenticity_token_arr[0].split('"')[1]
            login_form ={
                "authenticity_token":authenticity_token,
                "oauth_token":oauth_token,
                "session[username_or_email]":user_id,
                "session[password]":user_pwd
                }
            login_data = urllib.urlencode(login_form)
            rep2 = urlfetch.fetch(url=oauth_url,
                                  payload=login_data,
                                  method=urlfetch.POST,
                                  headers={'Content-Type': 'application/x-www-form-urlencoded'})
##            logging.debug("rep2_status_code:%d"%rep2.status_code)
            return re.findall(' \d{7}', rep2.content)[0].strip()
    def getSearch(self, path, query):
        if path.startswith('/search'):
            if path.startswith('/search/'):
                urlsearch = 'http://search.twitter.com' + path[7:]
                if query:
                    urlsearch += '?' + query
                logging.debug('url_search = %s'%urlsearch)
            else:
                urlsearch = 'http://search.twitter.com' + path
                if query:
                    urlsearch += '?' + query
##                logging.debug('url_search = %s'%urlsearch)
            try:
                search_result = urlfetch.fetch(url = urlsearch,
                                               method = urlfetch.GET)
            except:
                logging.debug('search fetch error')
                self.response.set_status(404)
                return
            if search_result.status_code == 200:
                logging.debug('%d'%len(search_result.content))
                self.response.out.write(search_result.content)
            else:
                self.response.set_status(404)
        else:
            self.response.out.write("No Auth & Bad Request")

def main():
    application = webapp.WSGIApplication([('/.*', ApiHandler)],debug=True)
    run_wsgi_app(application)

if __name__ == "__main__":
    main()